﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace IBoLT
{
	class SystemDrawingHelper
	{
		// Конвертирование из Bitmap в BitmapImage (для использования библиотеки AForge)
		public static System.Windows.Media.Imaging.BitmapImage BitmapToBitmapImage(Bitmap source)
		{
			System.IO.MemoryStream ms = new System.IO.MemoryStream();
			source.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
			ms.Position = 0;

			System.Windows.Media.Imaging.BitmapImage bi = new System.Windows.Media.Imaging.BitmapImage();
			bi.BeginInit();
			bi.StreamSource = ms;
			bi.EndInit();

			return bi;
		}

		public static System.Windows.Media.Imaging.BitmapSource loadBitmap(Bitmap source)
		{
			return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty,
				System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
		}


		// Конвертирование из BitmapImage в Bitmap (для использования библиотеки AForge)
		public static Bitmap BitmapImageToBitmap(System.Windows.Media.Imaging.BitmapSource source)
		{
			int width = source.PixelWidth;
			int height = source.PixelHeight;
			int stride = width * ((source.Format.BitsPerPixel + 7) / 8);

			byte[] bits = new byte[height * stride];

			System.IO.MemoryStream ms = new System.IO.MemoryStream();
			System.Windows.Media.Imaging.BitmapEncoder encoder = new System.Windows.Media.Imaging.BmpBitmapEncoder();
			encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(source));
			encoder.Save(ms);

			Bitmap bm = new Bitmap (ms);
			ms.Close();

			return bm;
		}

		internal static BitmapData LockImage(Bitmap Image) 
		{ 
			return Image.LockBits( new Rectangle(0, 0, Image.Width, Image.Height), ImageLockMode.ReadWrite, Image.PixelFormat); 
		}

		internal static void UnlockImage(Bitmap Image, BitmapData ImageData) 
		{
			Image.UnlockBits(ImageData);
		}

		internal static int GetPixelSize(BitmapData Data) 
		{
			if (Data.PixelFormat == PixelFormat.Format24bppRgb) 
				return 3;
			else if (Data.PixelFormat == PixelFormat.Format32bppArgb || Data.PixelFormat == PixelFormat.Format32bppPArgb || Data.PixelFormat == PixelFormat.Format32bppRgb) 
				return 4;
			return 0;
		}

		internal static unsafe Color GetPixel(BitmapData Data, int x, int y, int PixelSizeInBytes)
		{
			try
			{
				byte * DataPointer = (byte *)Data.Scan0;
				DataPointer = DataPointer + (y * Data.Stride) + (x * PixelSizeInBytes);
				
				if (PixelSizeInBytes == 3)
				{
					return Color.FromArgb(DataPointer[2], DataPointer[1], DataPointer[0]);
				}
				return Color.FromArgb(DataPointer[3], DataPointer[2], DataPointer[1], DataPointer[0]);
			}
			catch { throw ; }
		}

		internal static unsafe void SetPixel(BitmapData Data, int x, int y, Color PixelColor, int PixelSizeInBytes)
		{
			try
			{
				byte * DataPointer = (byte *)Data.Scan0;
				DataPointer = DataPointer + (y * Data.Stride) + (x * PixelSizeInBytes);
				
				if (PixelSizeInBytes == 3)
				{
					DataPointer[2] = PixelColor.R;
					DataPointer[1] = PixelColor.G;
					DataPointer[0] = PixelColor.B;
					return ;
				}
				
				DataPointer[3] = PixelColor.A;
				DataPointer[2] = PixelColor.R;
				DataPointer[1] = PixelColor.G;
				DataPointer[0] = PixelColor.B;
			}
			catch { throw ; }
		}

		// Суммирование двух цветов с учётом уровня каждого
		public static System.Drawing.Color AddBitmapRGB(System.Drawing.Color a, System.Drawing.Color b, Double lvlLeft, Double lvlRight)
		{
			int R = (int)Math.Max(0.0f, Math.Min(255.0f, lvlLeft * a.R + lvlRight * b.R));
			int G = (int)Math.Max(0.0f, Math.Min(255.0f, lvlLeft * a.G + lvlRight * b.G));
			int B = (int)Math.Max(0.0f, Math.Min(255.0f, lvlLeft * a.B + lvlRight * b.B));

			System.Drawing.Color result = System.Drawing.Color.FromArgb(R, G, B);

			return result;
		}
	}
}
